#include "oewalletselectwidget.h"
#include <QDebug>


#include <QPainter>
#include <QPixmap>
#include <QDir>
#include <QSettings>
#include <QToolButton>
#include <QSignalMapper>
#include <QVBoxLayout>
#include <QAction>
#include <QMenu>
#include <QFileDialog>
#include <QRegExpValidator>
#include "srdefine.h"
#include "OE/InputBox/oeinputbox_.h"
#include <OEMessageBox>
#include <OENotifyMessageBox>

OEWalletSelectWidget::OEWalletSelectWidget(QWidget *parent)
    : QWidget(parent)
{
    sizeWallet_ = QSize(200,60);
    /// attribute
    setWindowTitle(tr("wallet"));

//    resize(sizeWallet_.width(),0);

    // wallet info
    mapFileName_.insert("wallet", "wallet");
    // cryptographic seed
    mapFileName_.insert("seedname", "seed");

    // layout
    layout_ = new QVBoxLayout();
    layout_->setMargin(60);
    layout_->setSpacing(20);
    setLayout(layout_);

    mapper_ = new QSignalMapper(this);



    // link
    connect(mapper_, SIGNAL(mapped(QString)),
            this, SLOT(onHandoverWorkPath(QString)));

}

void OEWalletSelectWidget::clearWallet()
{
    listInfo_.clear();

    // 清理所有窗口
    while (auto item = layout_->takeAt(0)) {
        if (item) {
            layout_->removeItem(item);
            mapper_->removeMappings(item->widget());
            item->widget()->deleteLater();
        }
    }
}

int OEWalletSelectWidget::loadWallet(const QString &_path) {
    // check path
    if (!QDir(_path).exists())
        return -87;

    // clean wallet
    clearWallet();

    // load wallet info
    QStringList list_file_path = findWallet(_path);
    for (auto& filepath : list_file_path) {
        stWalletInfo info;
        if (0 != loadWalletInfo(filepath, info)) {
            qWarning() << QString("load %1 wallet error")
                            .arg(filepath);
        }
        listInfo_.push_back(info);
    }

    // create wallet widget;
    for(auto& info : listInfo_){
        if (0 != createWallet(info))
            qWarning() << QString("create %1 wallet error!")
                            .arg(info.name);
    }
    // create more wallet
    QToolButton* btn_more = new QToolButton();
    btn_more->setText(tr("+ 创建新钱包"));
    btn_more->setToolButtonStyle(Qt::ToolButtonStyle::ToolButtonTextUnderIcon);
    layout_->addWidget(btn_more);
    btn_more->setFixedSize(sizeWallet_);

    QToolButton* btn_restore_folder = new QToolButton();
    btn_restore_folder->setText(tr("+ 用文件恢复钱包"));
    btn_restore_folder->setToolButtonStyle(Qt::ToolButtonStyle::ToolButtonTextUnderIcon);
    layout_->addWidget(btn_restore_folder);
    btn_restore_folder->setFixedSize(sizeWallet_);

    QToolButton* btn_restore_cryptolalia = new QToolButton();
    btn_restore_cryptolalia->setText(tr("+ 用密语恢复钱包"));
    btn_restore_cryptolalia->setToolButtonStyle(Qt::ToolButtonStyle::ToolButtonTextUnderIcon);
    layout_->addWidget(btn_restore_cryptolalia);
    btn_restore_cryptolalia->setFixedSize(sizeWallet_);

    OENotifyManager *manager = new OENotifyManager();

    connect(btn_restore_cryptolalia, &QToolButton::clicked,
            this, &OEWalletSelectWidget::sigRestoreFromCryptolalia);
    // link more
    connect(btn_more, &QToolButton::clicked,
            this, &OEWalletSelectWidget::sigCreate);
    // link restore folder
    connect(btn_restore_folder, &QToolButton::clicked,
            this, [=]{
        QString file_path = QFileDialog::getExistingDirectory(this,
                                            tr("请选择文件夹钱包"),"..");
        if (file_path.isEmpty())
            return;
        QString crt_path = QDir::currentPath();
        QStringList list = file_path.split(crt_path);

        if (list.size() >= 2) {
#ifdef OEASYMESSAGE_H
            manager->notify("还原失败",tr("不可还原根钱包下的钱包"),":/ico/logo","");
#else
            qDebug() << "不可还原根钱包下的钱包";
#endif
            return;
        }

        bool bflag = this->isWallet(file_path);
        if (!bflag) {
#ifdef OEASYMESSAGE_H
            manager->notify("还原失败",tr("请选择正确的钱包文件夹"),":/ico/logo","");
//            OEMessageBox::BriefMessage(this, tr("请选择正确的钱包文件夹"));
#else
            qDebug() << "请选择正确的钱包文件夹";
#endif
            return;
        }
        emit this->sigRestoreFromFolder(file_path);
    });
//    connect()




//    setFixedSize(sizeWallet_.width(),sizeWallet_.height()* (listInfo_.count() + 2));
    return listInfo_.count();
}

int OEWalletSelectWidget::createWallet(
        const OEWalletSelectWidget::stWalletInfo &_info) {

    if (!QDir(_info.absPath).exists())
        return -1;
    QToolButton* wallet = new QToolButton();
//    wallet->setToolTip(_info.absPath);
    wallet->setToolTip(tr("点击可选择,按住可备份删除钱包"));

    // set button ico
//    if (!_info.logo.isEmpty()
//        && QFile(_info.logo).exists()) {
//        wallet->setToolButtonStyle(Qt::ToolButtonStyle::ToolButtonTextUnderIcon);
//        wallet->setIcon(QIcon(_info.logo));
//    }
    // set button menu
    wallet->setMenu(createWalletMenu(_info));
    wallet->setPopupMode(QToolButton::DelayedPopup);
    // set button name
    wallet->setText(_info.name);
    // set button sizes
    wallet->setFixedSize(sizeWallet_);

    // link wallet
    mapper_->setMapping(wallet, _info.absPath);
    connect(wallet, SIGNAL(clicked()),
            mapper_, SLOT(map()));

    layout_->addWidget(wallet);
    return 0;
}

int OEWalletSelectWidget::loadWalletInfo(const QString &_rootpath,
        OEWalletSelectWidget::stWalletInfo &_wallet) {
    const QString& wallet_config = _rootpath + "/" + mapFileName_["wallet"];
    if (!QFile(wallet_config).exists()){
        return 87;
    }
    QSettings setting(wallet_config,QSettings::IniFormat);

    _wallet.absPath = _rootpath;

    _wallet.name = setting.value("INFO/name").toString();

    _wallet.ekPubKey = setting.value("INFO/ek_pub_key").toString();

    // res
    _wallet.logo = setting.value("RES/logo").toString();
    convertPathToAbs(_rootpath, _wallet.logo);

    _wallet.logo_hover = setting.value("RES/logo_hover").toString();
    convertPathToAbs(_rootpath, _wallet.logo_hover);

    _wallet.logo_pressed = setting.value("RES/logo_pressed").toString();
    convertPathToAbs(_rootpath, _wallet.logo_pressed);


    // custom
    QString seed_path = setting.value("CUSTOM/seedpath").toString();
    if (!seed_path.isEmpty()) {
        if (QDir::isRelativePath(seed_path))
            seed_path = _rootpath + "/" + seed_path;

        mapFileName_["seedpath"] = seed_path;
    }

    QString seed_name = setting.value("CUSTOM/seedname").toString();
    if (!seed_name.isEmpty()) {
        mapFileName_["seedname"] = seed_name;
    }


    return 0;
}

QStringList OEWalletSelectWidget::findWallet(const QString &_path) {
    QDir dir(_path);
    if (!dir.exists())
        return {};

    // only dir
    dir.setFilter(QDir::Filter::Dirs |
                  QDir::Filter::NoDotAndDotDot);
    QFileInfoList list_dir = dir.entryInfoList();

    QStringList list_path;
    for (auto& dir_iter : list_dir) {
        bool bflag = isWallet(dir_iter.absoluteFilePath());
        if(bflag) {
            list_path.push_back(dir_iter.absoluteFilePath());
        }
    }
    return list_path;
}

bool OEWalletSelectWidget::convertPathToAbs(
        const QString &_rootPath, QString &_outpath)
{
    if (_outpath.isEmpty() || !QDir::isAbsolutePath(_rootPath))
        return false;

    if (QDir::isRelativePath(_outpath))
        _outpath = _rootPath + "/" + _outpath;

    return true;
}

bool OEWalletSelectWidget::createPixmap(const QString &_logo, QString &_logoHover, QString &_logoPressed)
{
    QPixmap pix_logo(_logo);
    if (pix_logo.isNull())
        return false;

    /// 制作暗色背景
    QPixmap temp_dim_pix(pix_logo.width(), pix_logo.height());

    temp_dim_pix.fill((QColor(0, 0, 0, 20)));
    QPainter p(&pix_logo);

    // draw hover png
    p.drawPixmap(0, 0, temp_dim_pix);
    if (_logoHover.isEmpty()) {
        _logoHover = QFile(_logo).fileName();
        _logoHover.insert(_logoHover.length() - 4, "_hover");
        if (!pix_logo.save(_logoHover))
            return false;
    }

    // draw pressed png
    p.drawPixmap(0, 0, temp_dim_pix);
    if (_logoPressed.isEmpty()) {
        _logoPressed = QFile(_logo).fileName();
        _logoPressed.insert(_logoPressed.length() - 4, "_pressed");
        if (!pix_logo.save(_logoPressed))
            return false;
    }

    return true;
}

bool OEWalletSelectWidget::isWallet(const QString &_path) {
    const QString& filepath = _path + "/" + mapFileName_["wallet"];
    if (!QFileInfo(filepath).exists() || !QFileInfo(filepath).isFile())
        return false;
    return true;
}
#include <OEInputBox>
QMenu *OEWalletSelectWidget::createWalletMenu(const stWalletInfo& _info)
{
    QMenu* menu = new QMenu();
    QAction* reset_action = new QAction(tr("重命名钱包"),menu);
    menu->addAction(reset_action);
    connect(reset_action, &QAction::triggered,
            this, [=]{
        OEInputBox_* w = new OEInputBox_;

        w->setEditLabel("钱包名称：");
        w->setEditPlaceholderText("请输入中文钱包名称");
        w->setEditEchoMode(QLineEdit::EchoMode::Normal);
        w->setEditValidator("^[\u4e00-\u9fa5]{0,16}$");
        w->resize(400,300);


        connect(w, &OEInputBox_::sigInputMsg,
                this, [=](const QString& _msg){
            const QString& file_name = _info.absPath + "/wallet";
            QSettings setting(file_name, QSettings::IniFormat);

//            setting.setValue("INFO/name",g_userName);
            setting.setValue("INFO/name", _msg);
            emit sigWalletNameChange(_info.name, _msg);
        });

        w->exec();
    });


    if (!_info.ekPubKey.isEmpty()) {
        QAction* export_action = new QAction(tr("导出公钥"),menu);
        menu->addAction(export_action);
        // link export wallet signal
        connect(export_action, &QAction::triggered,
                this, [=]{
            QString file_name = QFileDialog::getSaveFileName(this,
                                    tr("选择公钥保存地址"),"..");
            if (file_name.isEmpty())
                return;

            QFile file(file_name);
            if (file.open(QIODevice::WriteOnly)) {
                QTextStream in(&file);
                in << _info.ekPubKey;
                file.close();
            }
        });
    }
    else {
        QAction* export_action = new QAction(tr("无公钥"),menu);
        export_action->setEnabled(false);
        menu->addAction(export_action);
    }
    QAction* del_action = new QAction(tr("删除钱包"),menu);
    QAction* backup_action = new QAction(tr("备份钱包"),menu);
    menu->addAction(del_action);
    menu->addAction(backup_action);
    // link delete wallet signal
    connect(del_action, &QAction::triggered,
            this, [this, _info]{
#ifdef QT_DEBUG
        qDebug() << "delete wallet file path:" << _info.absPath;
#endif
        emit this->sigDelete(_info.name, _info.absPath);
    });
    // lin backup wallet signal
    connect(backup_action, &QAction::triggered,
            this, [this, _info]{
        QString file_path = QFileDialog::getExistingDirectory(this,
                        tr("选择钱包备份路径"), "..");
        if (file_path.isEmpty())
            return;
#ifdef QT_DEBUG
        qDebug() << "source file path: " << _info.absPath;
        qDebug() << "dest file path: " << file_path;
#endif
        QStringList a = file_path.split(_info.absPath);
        if (a.size() >= 2) {
#ifdef OEASYMESSAGE_H
            OEMessageBox::BriefMessage(this,tr("备份地址非法"));
#else
            qWarning(tr("备份地址非法"));
#endif
            return;
        }

        emit this->sigBackup(_info.absPath,file_path);
    });
    return menu;
}

bool OEWalletSelectWidget::onHandoverWorkPath(const QString &_absPath)
{
    if (!QDir(_absPath).exists()) {
        qCritical() << "invalid work path.";
        return false;
    }
#ifdef QT_DEBUG
    qDebug() << "current path :" << QDir::currentPath();
    qDebug() << "convert to path: " << _absPath;
#endif

    bool bflag = QDir::setCurrent(_absPath);

    if (bflag)
        emit sigFinshed(_absPath);

    return bflag;
}
